package sk.stuba.fiit.ltasys.web.mvc.model.dao.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import sk.stuba.fiit.ltasys.web.mvc.model.dao.ArchiveDao;
import sk.stuba.fiit.ltasys.web.mvc.model.entity.ArchivePackageEntity;
import sk.stuba.fiit.ltasys.web.mvc.model.entity.Configuration;
import sk.stuba.fiit.ltasys.web.mvc.model.entity.EvidenceRecordEntity;
import sk.stuba.fiit.ltasys.web.mvc.model.entity.TimestampEntity;
import sk.stuba.fiit.ltasys.web.mvc.model.entity.UserEntity;

@Repository("archiveDao")
@Transactional(readOnly = true)
public class ArchiveDaoImpl implements ArchiveDao{

	@Autowired
	protected SessionFactory sessionFactory = null;
	
	@Autowired
	public void setSessionFactory(SessionFactory sessionFactory) {
		template = new HibernateTemplate(sessionFactory);
	}
	
	protected HibernateTemplate template = null;
	
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void saveArchivePackage(ArchivePackageEntity archivePackage){
		template.saveOrUpdate(archivePackage);
	}
	
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void deleteArchivePackage(ArchivePackageEntity archivePackage){
		template.delete(archivePackage);
	}
	
	public ArchivePackageEntity loadArchivePackageByToken(String token){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		List<ArchivePackageEntity> result = null;
		if(token == null){
			result = session.createCriteria(ArchivePackageEntity.class).list();
		}else{
				result = session.createCriteria(ArchivePackageEntity.class).
				add(Restrictions.eq(ArchivePackageEntity.TOKEN, token)).list();
		}
		transaction.rollback();
		session.close();
		
		if( result.size()==0 )
			return new ArchivePackageEntity();
		return result.get(0);		
	}

	public List<ArchivePackageEntity> getAllArchivesByUser(UserEntity user) {
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		@SuppressWarnings("unchecked")
		List<ArchivePackageEntity> result = session.createCriteria(ArchivePackageEntity.class)
			.add(Restrictions.eq(ArchivePackageEntity.USER, user))
			.list();
		
		List<ArchivePackageEntity> resultList = new ArrayList<ArchivePackageEntity>();
		for (ArchivePackageEntity entity : result) {
			if(!resultList.contains(entity)){
				resultList.add(entity);
			}
		}
		
		
		transaction.rollback();
		session.close();
		return resultList;	
		
	}

	public EvidenceRecordEntity getArchiveRecordById(Integer id) {
		EvidenceRecordEntity evidenceRecord = template.get(EvidenceRecordEntity.class, id);
		return evidenceRecord;
	}

	public List<ArchivePackageEntity> getAllRecordForRetimestamping() {
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();

		GregorianCalendar calendar = new GregorianCalendar();
		String value = getConfigurateValue("retimestamping");
		Integer retimestampingTime; 
		try{
			retimestampingTime = Integer.valueOf(value);
		}catch(Exception e){
			retimestampingTime = 3;
		}
		calendar.add(Calendar.MONTH, retimestampingTime);
		List<TimestampEntity> tse = session.createCriteria(TimestampEntity.class).add(Restrictions.le("validTil", calendar.getTime()))
				.add(Restrictions.eq("leaf", true)).list();
		
		Set<Integer> idArchiv = new HashSet<Integer>();
		int i =0;
		for (TimestampEntity timestampEntity : tse) {
			idArchiv.add(timestampEntity.getArchiveRecord().getArchive_id());
			timestampEntity.setLeaf(false);
			session.saveOrUpdate(timestampEntity);
		}
		List<ArchivePackageEntity> resultList;
		if(idArchiv.size()> 0){
			resultList = session.createCriteria(ArchivePackageEntity.class)
				.add(Restrictions.in("archive_id", idArchiv )).list();		
		}
		else {
			resultList = new ArrayList<ArchivePackageEntity>();
		}
		transaction.commit();
		session.close();
		return resultList;	
	}

	public String getConfigurateValue(String key) {
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		List<Configuration> resultList = session.createCriteria(Configuration.class).add(Restrictions.eq("name", key)).list();
		transaction.rollback();
		session.close();
		if(resultList.size() >= 0){
			return resultList.get(0).getValue();
		}else{
			return null;
		}
	}
	
	
}
